/*
    This file is part of QTau
    Copyright (C) 2013-2018  Tobias "Tomoko" Platen <tplaten@posteo.de>
    Copyright (C) 2013       digited       <https://github.com/digited>
    Copyright (C) 2010-2013  HAL@ShurabaP  <https://github.com/haruneko>

    QTau is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    SPDX-License-Identifier: GPL-3.0+
*/

#include "ui/meter.h"
#include <ui/Config.h>

#include <qevent.h>
#include <qpainter.h>

#include <QPixmap>
#include <QTime>
#include "assert.h"
#include "tempomap.h"
#define __devloglevel__ 0

#include <QMessageBox>
#include "tempomap.h"

const int c_lblcache_hoff = 15;  // drawing offset from top-left of octave line
const int c_lblcache_voff = 10;

const QString c_lblcache_font = "Arial";

qtauMeterBar::qtauMeterBar(QWidget *parent) : QWidget(parent), _offset(0) {}

qtauMeterBar::~qtauMeterBar() {}

void qtauMeterBar::setOffset(int off) {
  if (off != _offset) {
    _offset = off;
    update();
  }
}

void qtauMeterBar::configure2(SNoteSetup &newSetup) {
  _ns = newSetup;
  int barScreenOffset = 0;
  int lastBar = 128;
  int scale = _ns.note.width() * 4;

  for (int i = 0; i <= lastBar; ++i) {
    fraction ts = _ns.tmap->getTimeSignatureForBar(i);
    _ns.barScreenOffsets[i] = barScreenOffset;
    barScreenOffset += scale * ts.numerator * 1.0 / ts.denominator;
  }

  // updateCache();
  update();
}

//---------------------------------------------------------

void qtauMeterBar::paintEvent(QPaintEvent *event) {
  // draw bg
  int hSt = event->rect().x() + _offset;
  int firstBar = _ns.getBarForScreenOffset(hSt);
  int lastBar = _ns.getBarForScreenOffset(hSt + event->rect().width());
  // if(lastBar==-1) resizeScore()

  QRect screenRect(event->rect());

  QPainter p(this);
  p.fillRect(screenRect, Qt::white);

  // prepare painting data
  int vSt = 0;
  int vEnd = geometry().height();
  int vMid = vEnd * 0.6;

  int bar = 0;
  int beat = 0;
  int pxOff = -_offset;

  QVector<QPoint> noteLines;
  QVector<QPoint> barLines;

  while (true) {
    if (bar > lastBar) break;

    fraction time = _ns.tmap->getTimeSignatureForBar(bar);  // 1

    if (beat == time.numerator)  // bar line
    {
      barLines.append(QPoint(pxOff, vSt));
      barLines.append(QPoint(pxOff, vEnd));
      beat = 1;
      bar++;
      time = _ns.tmap->getTimeSignatureForBar(bar);  // 2
    } else                                           // note line (low)
    {
      noteLines.append(QPoint(pxOff, vMid));
      noteLines.append(QPoint(pxOff, vEnd));
      beat++;
    }

    pxOff += _ns.note.width() * 4.0 / time.denominator;
  }

  p.setPen(QColor(cdef_color_inner_line));
  p.drawLines(noteLines);

  p.setPen(QColor(cdef_color_outer_line));
  p.drawLines(barLines);

  p.setPen(Qt::black);

  DEVLOG_DEBUG("firstBar " + STR(firstBar));
  DEVLOG_DEBUG("lastBar " + STR(lastBar));

  for (int i = firstBar; i <= lastBar; ++i) {
    int barScreenOffset = _ns.barScreenOffsets[i] - _offset;

    // QPainter p(this);
    int c_lblcache_font_size = 12;
    p.setFont(QFont(c_lblcache_font, c_lblcache_font_size));

    QRect lblR(barScreenOffset + 5, 0, 200, 20);
    QRect lblR2(barScreenOffset + 20, 0, 200, 20);
    QRect lblR3(barScreenOffset + 20, 21, 200, 20);

    // lblR.moveTop();
    QString s = QString("%1").arg(i + 1);
    QString s2 = _ns.tmap->getLabel(i, TM_BPM);
    QString s3 = _ns.tmap->getLabel(i, TM_SIG);

    p.drawText(lblR, s);
    if (s2.length()) p.drawText(lblR2, s2);
    if (s3.length()) p.drawText(lblR3, s3);
  }

  // if (!cachedLabels.isEmpty())
  //    p.drawPixmapFragments(cachedLabels.data(), cachedLabels.size(),
  //    *_labelCache);
}

void qtauMeterBar::resizeEvent(QResizeEvent *) {
  // updateCache();
}

void qtauMeterBar::mouseDoubleClickEvent(QMouseEvent *) {}

void qtauMeterBar::mouseMoveEvent(QMouseEvent *) {}

void qtauMeterBar::mousePressEvent(QMouseEvent *evt) {
  int x = evt->x() + _offset;
  int y = evt->y();
  int bar = _ns.getBarForScreenOffset(x);
  if (bar == -1) return;
  int mode = y - 20;
  if (mode < 0) {
    emit barClicked(bar, TM_BPM);
  }
  if (mode > 0) {
    emit barClicked(bar, TM_SIG);
  }
}

void qtauMeterBar::mouseReleaseEvent(QMouseEvent *) {
  //
}

void qtauMeterBar::wheelEvent(QWheelEvent *event) {
  if (event->modifiers() & Qt::ControlModifier)
    emit zoomed(event->delta());
  else
    emit scrolled(event->delta());
}

MeterBarLineEdit::MeterBarLineEdit() : QLineEdit() {}

void MeterBarLineEdit::keyPressEvent(QKeyEvent *event) {
  if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
    emit keyPressHooked(event->key());  // it works
  } else {
    // default handler for event
    QLineEdit::keyPressEvent(event);
  }
}
